﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Epsilon.Expr;

namespace Epsilon.Parse
{
    public partial class Parser
    {
        public FunctionExpr ParseFunction()
        {
            Token t = CurrentToken();
            if (CheckType(TokenType.Atom))
            {
                string name = t.Value;
                Chomp();
                List<FunctionArg> args = ParseFunctionArgs();
                Match(TokenType.Symbol, ":");
                Type ret = ParseType();
                Match(TokenType.Symbol, "->");
                List<Expression> body = ParseExprs();
                return new FunctionExpr(name, args, ret, body, t.Line, t.Col);
            }
            else
            {
                Error("Expecting a function name");
            }
            return null;
        }

        public FunExpr ParseFunExpr()
        {
            Token t = CurrentToken();
            Match(TokenType.Keyword, "fun");
            List<FunctionArg> args = ParseFunctionArgs();
            Match(TokenType.Symbol, "->");
            List<Expression> body = ParseExprs();
            Match(TokenType.Keyword, "end");
            return new FunExpr(args, body, t.Line, t.Col);
        }

        public List<FunctionArg> ParseFunctionArgs()
        {
            List<FunctionArg> args = new List<FunctionArg>();
            Match(TokenType.Symbol, "(");
            if (MatchPeek(TokenType.Symbol, ")"))
            {
                Chomp();
                return args;
            }
            args.Add(ParseFunctionArg());
            while (MatchPeek(TokenType.Symbol, ","))
            {
                Chomp();
                args.Add(ParseFunctionArg());
            }
            Match(TokenType.Symbol, ")");
            return args;
        }

        public FunctionArg ParseFunctionArg()
        {
            IPattern pattern = ParsePattern();
            Match(TokenType.Symbol, ":");
            Type type = ParseType();
            return new FunctionArg(pattern, type);
        }
    }
}
